home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Games / C-Pong / Original source / c-pong.c
Text File  |  1997-01-01  |  15KB  |  693 lines

  1.  
  2. /*            pong.c
  3.  The classic game of pong in Megamax C for the Mac.
  4.  Thanks to MacTutor (Vol 1, No. 5 April 1985 page 39) for 
  5.  animation techniques. If you are reading this and don't  
  6.  subscribe to MacTutor, consider it. No resource file is  
  7.  needed. This program, source and object, is in the
  8.  public domain and not for sale. 
  9.   
  10.  Author :    David L. O'Connor, 370 Eden St. Buffalo, N.Y. 
  11.             14220.  (716) 828-0898.   CIS - 70265,1172 
  12.  Date   :    July, 1985   Version 2
  13.  
  14.  
  15.  Changes by Ingemar 1996:
  16.  - Speed limit
  17.  - Keyboard equivalents
  18.  - Modern #includes
  19. */
  20.  
  21. /*
  22. #include    <MacTypes.h>
  23. #include    <MemoryMgr.h>
  24. #include    <QuickDraw.h>
  25. #include    <EventMgr.h>
  26. #include    <ToolBoxUtil.h>
  27. #include    <ResourceMgr.h>
  28. #include    <WindowMgr.h>
  29. #include    <MenuMgr.h>
  30. #include    <stdio.h>
  31. #include    <SoundMgr.h>
  32. #include    <SoundDvr.h>
  33. */
  34. #include    <Sound.h>
  35.  
  36. /* the game diRections */
  37. #define    STOPPED 0
  38. #define    UP 1
  39. #define    DOWN 2
  40. #define    LEFT 3
  41. #define    RIGHT 4
  42. #define    UP_LEFT 5
  43. #define    UP_RIGHT 6
  44. #define    DOWN_LEFT 7
  45. #define    DOWN_RIGHT 8
  46.  
  47. /* paddle + ball dimensions */
  48. #define    PADWIDTH 10
  49. #define    PADLENGTH 45
  50. #define    PADINSET 10
  51. #define    BALLWIDTH 9
  52. #define    BALLLENGTH 9
  53.  
  54. #define    BALLSPEED 7
  55. #define    PADDLESPEED 9
  56. #define    HIGHSCORE 21
  57.  
  58. /* the menu ids */
  59. #define    appleid 128    
  60. #define    fileid 129
  61. #define    editid 130
  62. #define    skillid 131
  63. #define    soundid 132
  64.  
  65. /* from the MAC's standard pattern list */
  66. #define    PAD_PAT ((*pat_Handle)->pat_list[6])
  67. #define    WALL_PAT ((*pat_Handle)->pat_list[10])
  68.  
  69. typedef struct {
  70.     int pat_cnt;
  71.     Pattern pat_list[38];
  72.     } sys_patterns;
  73.  
  74. typedef struct  {
  75.     Rect r;
  76.     int dir;
  77.     int speed;
  78.     int score;
  79.     } paddle;
  80.     
  81. typedef struct {
  82.     RgnHandle    Rgn;
  83.     RgnHandle    oldRgn;
  84.     RgnHandle    unRgn;
  85.     int dir;
  86.     int speed;
  87.     int on;
  88.     } target;
  89.  
  90. typedef struct {
  91.     int mode;
  92.     Tone triplet[1];
  93. } bleep_tag;
  94.         
  95. typedef struct {
  96.     int mode;
  97.     Tone triplet[2];
  98. } blat_tag;
  99.     
  100. static bleep_tag bleep_buf;
  101. static blat_tag  blat_buf;
  102. static paddle l_paddle, r_paddle;
  103. static target ball;
  104. static sys_patterns **pat_Handle;
  105. static WindowPtr gamewindow, which_window;
  106. static WindowRecord winstorage;
  107. static Rect r, dragRect, top_wall, bottom_wall;
  108. static EventRecord gameEvent;
  109. static MenuHandle gamemenu[5];
  110. static char menutitle[1];
  111. static int skill_level, done, paused, last_won, volleys, sound_on;
  112. static unsigned char title[] = { 65,
  113.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  114.                         'L','e','f','t',' ',' ','0','0',
  115.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  116.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  117.                         'M','A','C','_','P','o','n','g',
  118.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  119.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  120.                         'R','i','g','h','t',' ','0','0',
  121.                         ' ',' ',' ',' ',' ',' ',' ',' ', 
  122.                         '\0'};
  123.  
  124. /* Every so often, let the Mac's paddle fail to track the ball until
  125.    the ball has passed it by a certain amount.
  126.    This is the heart of a satisfying game. */
  127. int handicap()
  128. {
  129.     register mac_skill;
  130.  
  131.     switch(skill_level) {
  132.         case 1 :
  133.             mac_skill = 2;
  134.         break;
  135.         case 2 :
  136.             mac_skill = 8;
  137.         break;
  138.         case 3 :
  139.             mac_skill = 27;
  140.         break;
  141.         case 4 :
  142.             mac_skill = 64;
  143.         break;
  144.         default :
  145.             mac_skill = 2;
  146.         break;
  147.     }
  148.     return ((Random() % mac_skill) == 0) ? 5 : 0;
  149. }
  150.  
  151. void blat()
  152. {
  153.     if (sound_on) {
  154.         if (! SoundDone())
  155.             StopSound();
  156.         StartSound((Ptr) &blat_buf, (long) sizeof(blat_buf), nil);
  157.     }
  158. }
  159.  
  160. void bleep()
  161. {
  162.     if (sound_on) {
  163.         if (! SoundDone())
  164.             StopSound();
  165.         StartSound((Ptr) &bleep_buf, (long) sizeof(bleep_buf), nil);
  166.     }
  167. }
  168.  
  169. void display_score()
  170. {
  171.     static long i;
  172.     
  173.             i = l_paddle.score;
  174.             title[15]=0x30+(i/100);
  175.             title[16]=0x30+((i%100)/10);
  176.             title[17]=0x30+(i%10);
  177.             i = r_paddle.score;
  178.             title[63]=0x30+(i/100);
  179.             title[64]=0x30+((i%100)/10);
  180.             title[65]=0x30+(i%10);
  181.         SetWTitle(gamewindow, title);
  182. }
  183.  
  184. /* the ball eats the walls and paddles */
  185. void recover_from_collision()
  186. {
  187.     register Rect *rp = &((**ball.unRgn).rgnBBox);
  188.  
  189.     if (SectRect(rp, &top_wall, &r))
  190.         FillRect(&r, WALL_PAT);
  191.     else if (SectRect(rp, &bottom_wall, &r))
  192.         FillRect(&r, WALL_PAT);
  193.     if (SectRect(rp, &l_paddle.r, &r))
  194.         FillRect(&r, PAD_PAT);
  195.     else if (SectRect(rp, &r_paddle.r, &r))
  196.         FillRect(&r, PAD_PAT);
  197. }
  198.  
  199. void move_ball()
  200. {
  201.     if (ball.on) {
  202.         CopyRgn(ball.Rgn, ball.oldRgn);
  203.         switch (ball.dir) {
  204.             case LEFT:
  205.                 OffsetRgn(ball.Rgn, -ball.speed, 0);
  206.             break;
  207.             case RIGHT:
  208.                 OffsetRgn(ball.Rgn, ball.speed, 0);
  209.             break;
  210.             case UP_LEFT:
  211.                 OffsetRgn(ball.Rgn, -ball.speed, -ball.speed);
  212.             break;
  213.             case UP_RIGHT:
  214.                 OffsetRgn(ball.Rgn, ball.speed, -ball.speed);
  215.             break;
  216.             case DOWN_LEFT:
  217.                 OffsetRgn(ball.Rgn, -ball.speed, ball.speed);
  218.             break;
  219.             case DOWN_RIGHT:
  220.                 OffsetRgn(ball.Rgn, ball.speed, ball.speed);
  221.             break;
  222.         }
  223.         UnionRgn(ball.Rgn, ball.oldRgn, ball.unRgn);
  224.         DiffRgn(ball.unRgn, ball.Rgn, ball.unRgn);
  225.         EraseRgn(ball.unRgn);
  226.         PaintRgn(ball.Rgn);
  227.         recover_from_collision();
  228.     }
  229. }
  230.  
  231. void move_right_paddle()
  232. {
  233.     if (r_paddle.dir == STOPPED)
  234.         FillRect(&r_paddle.r, PAD_PAT);
  235.     else {
  236.         r.left = r_paddle.r.left;
  237.         r.right = r_paddle.r.right;
  238.         switch (r_paddle.dir) {
  239.             case UP:
  240.                 r.bottom = r_paddle.r.bottom;
  241.                 r_paddle.r.top -= r_paddle.speed;
  242.                 r_paddle.r.bottom -= r_paddle.speed;
  243.                 r.top = r_paddle.r.bottom;
  244.             break;
  245.             case DOWN:
  246.                 r.top = r_paddle.r.top;
  247.                 r_paddle.r.top += r_paddle.speed;
  248.                 r_paddle.r.bottom += r_paddle.speed;
  249.                 r.bottom = r_paddle.r.top;
  250.             break;    
  251.         }
  252.         EraseRect(&r); 
  253.         FillRect(&r_paddle.r, PAD_PAT);
  254.     }
  255. }
  256.  
  257. void move_left_paddle()
  258. {
  259.     static Point mouseloc;
  260.     register int newtop, newbottom;
  261.  
  262.     GetMouse(&mouseloc);
  263.     if (mouseloc.v != l_paddle.r.top) {
  264.         r.left = l_paddle.r.left;
  265.         r.right = l_paddle.r.right;
  266.         if (mouseloc.v <= winstorage.port.portRect.top) {
  267.             newtop = winstorage.port.portRect.top;
  268.             newbottom = newtop + PADLENGTH;
  269.         }
  270.         else if (mouseloc.v + PADLENGTH >= winstorage.port.portRect.bottom) {
  271.             newbottom = winstorage.port.portRect.bottom;
  272.             newtop = newbottom - PADLENGTH;
  273.         }
  274.         else {
  275.             newtop = mouseloc.v;
  276.             newbottom = newtop + PADLENGTH;
  277.         }
  278.         if (newtop > l_paddle.r.top) {
  279.             r.top = l_paddle.r.top;
  280.             r.bottom = (newtop > l_paddle.r.bottom) ? l_paddle.r.bottom : newtop;
  281.         }
  282.         else if (newtop < l_paddle.r.top) {
  283.             r.bottom = l_paddle.r.bottom;
  284.             r.top = (newbottom < l_paddle.r.top) ? l_paddle.r.top : newbottom;
  285.         }
  286.         l_paddle.r.top = newtop;
  287.         l_paddle.r.bottom = newbottom;
  288.         EraseRect(&r); 
  289.         FillRect(&l_paddle.r, PAD_PAT);
  290.     }
  291.     else
  292.         FillRect(&l_paddle.r, PAD_PAT);
  293. }
  294.  
  295. /* someone scored a point */
  296. void kill_ball()
  297. {
  298.     ball.on = volleys = 0;
  299.     CopyRgn(ball.Rgn, ball.unRgn);
  300.     EraseRgn(ball.Rgn);
  301.     recover_from_collision();
  302.     blat();
  303.     display_score();
  304. }
  305.  
  306. /* check for bounces, diRection changes, scoring, etc */
  307. void check_status()
  308. {
  309.     static Rect *ball_r;
  310.  
  311.     register ball_top        = (**ball.Rgn).rgnBBox.top;
  312.     register ball_bottom    = (**ball.Rgn).rgnBBox.bottom;
  313.     register ball_left        = (**ball.Rgn).rgnBBox.left;
  314.     register ball_right        = (**ball.Rgn).rgnBBox.right;
  315.     
  316.     ball_r = &((**ball.Rgn).rgnBBox);
  317.  
  318.     /* make it a little harder as time goes by */
  319.     if (volleys > 35)
  320.         ball.speed = BALLSPEED + 6;
  321.     else if (volleys > 30)
  322.         ball.speed = BALLSPEED + 5;
  323.     else if (volleys > 25)
  324.         ball.speed = BALLSPEED + 4;
  325.     else if (volleys > 20)
  326.         ball.speed = BALLSPEED + 3;
  327.     else if (volleys > 15)
  328.         ball.speed = BALLSPEED + 2;
  329.     else if (volleys > 10)
  330.         ball.speed = BALLSPEED + 1;
  331.         
  332.     r_paddle.speed = ball.speed + 2;
  333.         
  334.     /* the right paddle tries to track the ball */
  335.     if ( (ball_right > 250) &&
  336.          (ball.dir == UP_RIGHT || ball.dir == DOWN_RIGHT || 
  337.           ball.dir == RIGHT) ) {
  338.         if (ball_top + handicap() < r_paddle.r.top)
  339.             r_paddle.dir = UP;
  340.         else if (ball_bottom - handicap() > r_paddle.r.bottom)
  341.             r_paddle.dir = DOWN;
  342.         else
  343.             r_paddle.dir = STOPPED;
  344.     }
  345.     else
  346.         r_paddle.dir = STOPPED;
  347.         
  348.     /* the ball and the left boundry */
  349.     if (ball_left < l_paddle.r.right ) {
  350.         if (SectRect(ball_r, &l_paddle.r, &r)) {
  351.             volleys++;
  352.             bleep();
  353.             if (ball_top <= l_paddle.r.top + 15)
  354.                 ball.dir = UP_RIGHT;
  355.             else if (ball_top > l_paddle.r.top + 15 && ball_bottom < l_paddle.r.top + 30)
  356.                 ball.dir = RIGHT;
  357.             else
  358.                 ball.dir = DOWN_RIGHT;
  359.         }
  360.         else {
  361.             last_won = RIGHT;
  362.             r_paddle.score++;
  363.             kill_ball();
  364.         }
  365.         return;
  366.     }
  367.     
  368.     /* the ball and the right boundry */
  369.     if (ball_right > r_paddle.r.left) {
  370.         if (SectRect(ball_r, &r_paddle.r, &r)) {
  371.             volleys++;
  372.             bleep();
  373.             if (ball_top <= r_paddle.r.top + 15)
  374.                 ball.dir = UP_LEFT;
  375.             else if (ball_top > r_paddle.r.top + 15 && ball_bottom < r_paddle.r.top + 30)
  376.                 ball.dir = LEFT;
  377.             else
  378.                 ball.dir = DOWN_LEFT;
  379.         }
  380.         else {
  381.             last_won = LEFT;
  382.             l_paddle.score++;
  383.             kill_ball();
  384.         }
  385.         return;
  386.     }
  387.     
  388.     /* the ball and the top wall */
  389.     if (ball_top < top_wall.bottom) {
  390.         if (ball.dir == UP_LEFT)
  391.             ball.dir = DOWN_LEFT;
  392.         else if (ball.dir == UP_RIGHT)
  393.             ball.dir = DOWN_RIGHT;
  394.         bleep();
  395.         return;
  396.     }
  397.     
  398.     /* the ball and the bottom wall */
  399.     if (ball_bottom > bottom_wall.top) {
  400.         if (ball.dir == DOWN_LEFT)
  401.             ball.dir = UP_LEFT;
  402.         else if (ball.dir == DOWN_RIGHT)
  403.             ball.dir = UP_RIGHT;
  404.         bleep();
  405.         return;
  406.     }
  407. }
  408.  
  409. void Init_game()
  410. {
  411.     l_paddle.score = r_paddle.score = 0;
  412.     ball.speed = BALLSPEED;
  413.     kill_ball();
  414. }
  415.  
  416. void serve_ball()
  417. {
  418.     register i;
  419.  
  420.     OffsetRgn(ball.Rgn, 250 - ((**ball.Rgn).rgnBBox.right),
  421.                         150 - ((**ball.Rgn).rgnBBox.top) );
  422.     for (i = 0; i < 250; i++) {
  423.         check_status();
  424.         move_right_paddle();
  425.         move_left_paddle();
  426.         move_ball();
  427.     }
  428.     ball.dir = (last_won == RIGHT) ? LEFT : RIGHT;
  429.     ball.speed = BALLSPEED;
  430.     ball.on = 1;
  431.     PaintRgn(ball.Rgn);
  432.     bleep();
  433. }
  434.  
  435. void create_ball()
  436. {
  437.     ball.Rgn = NewRgn();
  438.     ball.oldRgn = NewRgn();
  439.     ball.unRgn = NewRgn();
  440.     ball.dir = LEFT;
  441.     ball.speed = BALLSPEED;
  442.     SetRect (&r, 250,  150, 250 + BALLWIDTH, 150 + BALLLENGTH);
  443.     OpenRgn();
  444.     FrameOval(&r);
  445.     CloseRgn(ball.Rgn);
  446. }
  447.  
  448. void create_walls()
  449. {
  450.     SetRect(&top_wall,
  451.             winstorage.port.portRect.left + 20,
  452.             winstorage.port.portRect.top + 5,
  453.             winstorage.port.portRect.right - 20, 
  454.             winstorage.port.portRect.top + 20);
  455.     FillRect(&top_wall, WALL_PAT);
  456.     SetRect(&bottom_wall,
  457.             winstorage.port.portRect.left + 20,
  458.             winstorage.port.portRect.bottom - 20,
  459.             winstorage.port.portRect.right - 20,
  460.             winstorage.port.portRect.bottom - 5);
  461.     FillRect(&bottom_wall, WALL_PAT);    
  462. }
  463.  
  464. void create_r_paddle()
  465. {    
  466.     r_paddle.dir = STOPPED;
  467.     r_paddle.speed = PADDLESPEED;
  468.     r_paddle.score = 0;
  469.     SetRect (&r_paddle.r,
  470.             winstorage.port.portRect.right - PADWIDTH - PADINSET,
  471.             winstorage.port.portRect.top + PADINSET,
  472.             winstorage.port.portRect.right - PADWIDTH - PADINSET + PADWIDTH,
  473.             winstorage.port.portRect.top + PADINSET + PADLENGTH);
  474.     FillRect(&r_paddle.r, PAD_PAT);    
  475. }    
  476.  
  477. void create_l_paddle()
  478. {    
  479.     l_paddle.dir = STOPPED;
  480.     l_paddle.speed = PADDLESPEED;
  481.     l_paddle.score = 0;
  482.     SetRect (&l_paddle.r, 
  483.             winstorage.port.portRect.left + PADINSET,
  484.             winstorage.port.portRect.top + PADINSET,
  485.             winstorage.port.portRect.left + PADINSET + PADWIDTH,
  486.             winstorage.port.portRect.top + PADINSET + PADLENGTH);
  487.     FillRect(&l_paddle.r, PAD_PAT);
  488. }
  489.  
  490. void DoCommand(long menu_selection)
  491. {
  492.     register int the_item;
  493.     static unsigned char name[256];
  494.     
  495.     the_item = LoWord(menu_selection);
  496.     switch (HiWord(menu_selection))
  497.     {
  498.         case appleid :
  499.             GetItem(gamemenu[0], the_item, name);
  500.             OpenDeskAcc(name);
  501.             SetPort(gamewindow);
  502.         break;
  503.         case editid:
  504.             SystemEdit(the_item - 1);
  505.         break;
  506.         case fileid:
  507.             switch (the_item) {
  508.                 case 1 :
  509.                     if (paused) {
  510.                         paused = 0;
  511.                         SetItem(gamemenu[1], 1, "\pPause");
  512.                     }
  513.                     else {
  514.                         paused = 1;
  515.                         SetItem(gamemenu[1], 1, "\pContinue");
  516.                     }
  517.                 break;
  518.                 case 2:
  519.                     Init_game();
  520.                 break;
  521.                 case 3 :
  522.                     done = 1;
  523.                 break;
  524.             }
  525.         break;
  526.         case skillid :
  527.             CheckItem(gamemenu[3], skill_level, 0);
  528.             skill_level = the_item;
  529.             CheckItem(gamemenu[3], skill_level, 1);
  530.         break;
  531.         case soundid:
  532.             if (sound_on) {
  533.                 sound_on = 0;
  534.                 SetItem(gamemenu[4], 1, "\pSound On");
  535.                     }
  536.             else {
  537.                 sound_on = 1;
  538.                 SetItem(gamemenu[4], 1, "\pSound Off");
  539.             }
  540.         break;
  541.     }
  542.     HiliteMenu(0);
  543. }
  544.  
  545. void enable_edit_menu()
  546. {
  547.     EnableItem(gamemenu[2], 1);
  548.     EnableItem(gamemenu[2], 3);
  549.     EnableItem(gamemenu[2], 4);
  550.     EnableItem(gamemenu[2], 5);
  551.     EnableItem(gamemenu[2], 6);
  552. }
  553.  
  554. void disable_edit_menu()
  555. {
  556.     DisableItem(gamemenu[2], 1);
  557.     DisableItem(gamemenu[2], 3);
  558.     DisableItem(gamemenu[2], 4);
  559.     DisableItem(gamemenu[2], 5);
  560.     DisableItem(gamemenu[2], 6);
  561. }
  562.  
  563. void build_menus()
  564. {
  565.     register int i;
  566.     
  567.     InitMenus();
  568.     gamemenu[0] = NewMenu(appleid, "\p");
  569.     gamemenu[1] = NewMenu(fileid, "\pFile");
  570.     gamemenu[2] = NewMenu(editid, "\pEdit");
  571.     gamemenu[3] = NewMenu(skillid, "\pSkill");
  572.     gamemenu[4] = NewMenu(soundid, "\pSound");
  573.     AddResMenu(gamemenu[0],'DRVR');
  574.     AppendMenu(gamemenu[1],"\pPause/P;Restart/R;Quit/Q");
  575.     AppendMenu(gamemenu[2],"\p(Undo;(-;(Cut;(Copy;(Paste;(Clear");
  576.     AppendMenu(gamemenu[3],"\pBeginner;Novice;Normal;Expert");
  577.     AppendMenu(gamemenu[4],"\pSound Off/S");
  578.     for(i = 0; i < 5; i++)
  579.         InsertMenu(gamemenu[i], 0);
  580.     CheckItem(gamemenu[3], skill_level, 1);
  581.     DrawMenuBar();
  582. }
  583.  
  584. void InitSounds() {
  585.     bleep_buf.mode = swMode;
  586.     bleep_buf.triplet[0].count = 1000;
  587.     bleep_buf.triplet[0].amplitude = 255;
  588.     bleep_buf.triplet[0].duration = 5;
  589.     blat_buf.mode = swMode;
  590.     blat_buf.triplet[0].count = 1000;
  591.     blat_buf.triplet[0].amplitude = 255;
  592.     blat_buf.triplet[0].duration = 5;
  593.     blat_buf.triplet[1].count = 3000;
  594.     blat_buf.triplet[1].amplitude = 255;
  595.     blat_buf.triplet[1].duration = 10; 
  596. }
  597.  
  598. void play_pong()
  599. {
  600. long startTicks;
  601.  
  602.     if ( (! paused) && (l_paddle.score < HIGHSCORE && r_paddle.score < HIGHSCORE))
  603.     {
  604.         startTicks = TickCount();
  605.         if (! ball.on)
  606.             serve_ball();
  607.         check_status();
  608.         move_left_paddle();
  609.         move_right_paddle();
  610.         move_ball();
  611.         
  612.         while (startTicks == TickCount());
  613.     }
  614. }
  615.  
  616. /* pretty much straight from SAMP in I.M. */
  617. void Handle_Events()
  618. {
  619.     SystemTask();
  620.     if (GetNextEvent(everyEvent, &gameEvent)) {
  621.         switch (gameEvent.what) {
  622.             case mouseDown :
  623.                 switch (FindWindow(gameEvent.where, &which_window)) {
  624.                     case inMenuBar :
  625.                         DoCommand(MenuSelect(gameEvent.where));
  626.                     break;
  627.                     case inSysWindow :
  628.                         SystemClick(&gameEvent, which_window);
  629.                     break;
  630.                     case inDrag :
  631.                         DragWindow(which_window, gameEvent.where, &dragRect);
  632.                     break;
  633.                     case inContent :
  634.                         if (which_window != FrontWindow())
  635.                             SelectWindow(which_window);
  636.                     break;
  637.                 }
  638.             break;
  639.             case updateEvt :
  640.                 SetPort(gamewindow);
  641.                 BeginUpdate(gamewindow);
  642.                 FillRect(&l_paddle.r, PAD_PAT);
  643.                 FillRect(&r_paddle.r, PAD_PAT);
  644.                 FillRect(&top_wall, WALL_PAT);
  645.                 FillRect(&bottom_wall, WALL_PAT);
  646.                 if (ball.on)
  647.                     PaintRgn(ball.Rgn);
  648.                 EndUpdate(gamewindow);
  649.             break;
  650.         }
  651.     }
  652. } // Handle_Events
  653.  
  654. void setup()
  655. {
  656.     done = 0;
  657.     skill_level = 2;
  658.     sound_on = 1;
  659.     last_won = RIGHT;
  660.     InitGraf(&thePort);
  661.     InitFonts();
  662.     InitWindows();
  663.     TEInit();
  664.     InitDialogs(0);
  665.     InitCursor();
  666.     InitSounds();
  667.     pat_Handle = (sys_patterns**) GetResource('PAT#', 0);
  668.     FlushEvents(everyEvent, 0);
  669.     SetRect(&r, 4, 40, 508, 338);
  670.     SetRect(&dragRect, 4, 24, r.right - 4, r.bottom - 4);
  671.     gamewindow = NewWindow(&winstorage, &r, title, 1, 0L, (WindowPtr)-1L, 0, 0L);
  672.     SetPort(gamewindow);
  673.     build_menus();
  674.     ShowCursor();
  675.     create_l_paddle();
  676.     create_r_paddle();
  677.     create_walls();
  678.     create_ball();
  679.     Init_game();
  680. }
  681.  
  682. void main() 
  683. {
  684.     setup();
  685.     while (! done) {
  686.         Handle_Events();
  687.         play_pong();
  688.     }
  689.     FlushEvents(everyEvent, 0);
  690.     StopSound();
  691.     ExitToShell();
  692. }
  693.